#ifndef SALIENCY_H_INCLUDED
#define SALIENCY_H_INCLUDED

#include "Process/observer.hpp"
#include "Process/process.hpp"

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#define sqr(X) X*X

using namespace cv;
using namespace std;

typedef unsigned long DWORD; 
typedef unsigned short WORD;
typedef void *HANDLE;
typedef unsigned char byte;

typedef vector<string> vecS;
typedef vector<int> vecI;
typedef vector<float> vecF;
typedef vector<double> vecD;
typedef pair<double, int> CostIdx;
typedef pair<float, int> CostfIdx;

//template<typename T> inline T sqr(T x) { return x * x;}
template<class T> inline T vecDist3(const Vec<T, 3> &v1, const Vec<T, 3> &v2) {return sqrt(sqr(v1[0] - v2[0])+sqr(v1[1] - v2[1])+sqr(v1[2] - v2[2]));}
template<class T> inline T vecSqrDist3(const Vec<T, 3> &v1, const Vec<T, 3> &v2) {return sqr(v1[0] - v2[0])+sqr(v1[1] - v2[1])+sqr(v1[2] - v2[2]);}
//template<class T1, class T2> inline void operator /= (Vec<T1, 3> &v1, const T2 v2) { v1[0] /= v2; v1[1] /= v2; v1[2] /= v2; }
template<class T> inline T pntSqrDist(const Point_<T> &p1, const Point_<T> &p2) {return sqr(p1.x - p2.x) + sqr(p1.y - p2.y);}

#define CV_Assert_(expr, args) \
{\
	if(!(expr)) {\
	string msg = cv::format args;\
	cv::error(cv::Exception(CV_StsAssert, msg, __FUNCTION__, __FILE__, __LINE__) ); }\
}

class Saliency :public Observer
{
public:
	Saliency(Process *pro);
	~Saliency();
	 
	void Update(Image &image);

	static Mat GetFT(const Mat &img3f);

	// Histogram Contrast of [3]
	static Mat GetHC(const Mat &img3f);

	// Region Contrast 
	//static Mat GetRC(const Mat &img3f);
	//static Mat GetRC(const Mat &img3f, double sigmaDist, double segK, int segMinSize, double segSigma);

	// Luminance Contrast [2]
	static Mat GetLC(const Mat &img3f);

	// Spectral Residual [4]
	static Mat GetSR(const Mat &img3f);
	
	// Color quantization
	static int Quantize(const Mat& img3f, Mat &idx1i, Mat &_color3f, Mat &_colorNum, double ratio = 0.95);
	
	Mat out;
	int type;
private:
	static const int SAL_TYPE_NUM = 4;
	typedef Mat (*GET_SAL_FUNC)(const Mat &);
	static const char* SAL_TYPE_DES[SAL_TYPE_NUM];
	static const GET_SAL_FUNC gFuns[SAL_TYPE_NUM];
	
	static void GetHC(const Mat &binColor3f, const Mat &weights1f, Mat &colorSaliency);

	static void SmoothSaliency(const Mat &binColor3f, Mat &sal1d, float delta, const vector< vector<CostfIdx> > &similar);
	static void AbsAngle(const Mat& cmplx32FC2, Mat& mag32FC1, Mat& ang32FC1);
	static void GetCmplx(const Mat& mag32F, const Mat& ang32F, Mat& cmplx32FC2);
};
#endif // SALIENCY_H_INCLUDED
